package com.yonyou.pmclouds.reason.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.consts.EnableStatusConst;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.exception.IllegalRequestArgException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.CodeNameUtils;
import com.yonyou.pmclouds.basecom.util.ExcelUtil;
import com.yonyou.pmclouds.reason.entity.ProblemReasonVO;
import com.yonyou.pmclouds.reason.model.ProblemReasonManager;
import com.yonyou.pmclouds.reason.rmiitf.ProblemReasonMaintain;
import com.yonyou.pmclouds.reason.rmiitf.ProblemReasonQuery;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RequestMapping("/problemReason")
@RestController
public class ProblemReasonController {
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProblemReasonQuery query;
    @Reference(version = ApplicationConsts.APPLICATION_VERSION)
    private ProblemReasonMaintain maintain;
    @Autowired
    private ProblemReasonManager manager;

    public static final int STATUS_NOT_REF = 0;
    public static final int STATUS_REF_BY_CHILD = 1;
    public static final int STATUS_REF_BY_BILL = 2;

    @GetMapping("/list")
    public ProblemReasonVO[] getTenantProblemReasons(@RequestParam(value = "status", required = false) Integer status,
                                                     @RequestParam("category") Integer category) throws BusinessException {
        if (category != ProblemReasonVO.CATEGORY_QUALITY && category != ProblemReasonVO.CATEGORY_SECURITY)
            throw new BusinessException("问题原因类别传参错误");

        byte enableStatus = EnableStatusConst.ENABLE;
        if(status != null)
            enableStatus = status.byteValue();

        ProblemReasonVO[] allVOs = query.queryReasonByTenant(RuntimeEnvironment.getTenantId(), enableStatus, category.byteValue());
        //  前端要树，那就构造树吧
        if (ArrayUtils.isEmpty(allVOs)) {
            return allVOs;
        }
        // 构造树
        Map<String, List<ProblemReasonVO>> reasonChildMap = new HashMap<>();
        Map<String, String> reasonCodeMap = new HashMap<>();
        for (ProblemReasonVO vo : allVOs) {
            reasonCodeMap.put(vo.getPkReason(), vo.getScode());
        }
        for (ProblemReasonVO vo : allVOs) {
            String parent = vo.getPkParent();
            if (StringUtils.isEmpty(parent)) {
                parent = StringUtils.EMPTY;
            } else{
                //前端需要子节点中存放父节点的编码
                vo.setPcode(reasonCodeMap.get(parent));
            }
            List<ProblemReasonVO> children = reasonChildMap.get(parent);
            if (children == null) {
                children = new ArrayList<>();
                reasonChildMap.put(parent, children);
            }
            children.add(vo);
        }
        for (ProblemReasonVO vo : allVOs) {
            List<ProblemReasonVO> children = reasonChildMap.get(vo.getPkReason());
            if (children != null) {
                vo.setChildReason(children.toArray(new ProblemReasonVO[children.size()]));
            }
        }
        List<ProblemReasonVO> result = reasonChildMap.get(StringUtils.EMPTY);
        if (result == null) {
            return new ProblemReasonVO[0];
        } else {
            return result.toArray(new ProblemReasonVO[result.size()]);
        }
    }

    @PostMapping("/insert")
    public ProblemReasonVO insert(@RequestBody @Validated(ProblemReasonVO.InsertValid.class) ProblemReasonVO reasonVO,
                              BindingResult errors) throws BusinessException {
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        reasonVO.setSname(StringUtils.trim(reasonVO.getSname()));
        // 校验名称和编码的合法性
        if (CodeNameUtils.checkCodeStr(reasonVO.getScode()) >= 0 || CodeNameUtils.checkNameStr(reasonVO.getSname(), null) >= 0) {
            throw new IllegalRequestArgException();
        }
        reasonVO.setPkTenant(RuntimeEnvironment.getTenantId());
        String id = maintain.insert(reasonVO);
        ProblemReasonVO vo = query.getById(id);
        return buildPcode(vo);
    }

    @PostMapping("/update")
    public ProblemReasonVO update(@RequestBody @Validated(ProblemReasonVO.UpdateValid.class) ProblemReasonVO reasonVO,
                              BindingResult errors) throws BusinessException {
        if (errors.hasErrors()) {
            throw new IllegalRequestArgException();
        }
        reasonVO.setSname(StringUtils.trim(reasonVO.getSname()));
        if (CodeNameUtils.checkNameStr(reasonVO.getSname(), null) >= 0) {
            throw new IllegalRequestArgException();
        }
        String id = maintain.update(reasonVO);
        ProblemReasonVO vo = query.getById(id);
        return buildPcode(vo);
    }

    @PostMapping("/delete")
    public ProblemReasonVO delete(@RequestBody ProblemReasonVO reasonVO) throws BusinessException {
        if (StringUtils.isEmpty(reasonVO.getPkReason()) || StringUtils.isEmpty(reasonVO.getChangeFlag())) {
            throw new IllegalRequestArgException();
        }
        String id = maintain.delete(reasonVO.getPkReason(), reasonVO.getChangeFlag());
        return reasonVO;
    }

    //设置父级code用于前端展示
    private ProblemReasonVO buildPcode(ProblemReasonVO vo) throws BusinessException {
        if(vo == null || StringUtils.isBlank(vo.getPkParent())) return vo;

        String parent = vo.getPkParent();
        ProblemReasonVO pvo = query.getById(parent);
        if(pvo != null) vo.setPcode(pvo.getScode());

        return vo;
    }

    @PostMapping("/disable")
    public ProblemReasonVO disable(@RequestBody ProblemReasonVO reasonVO) throws BusinessException{
        if(reasonVO == null) throw new BusinessException("传参错误");

        return maintain.disable(reasonVO);

    }
    @PostMapping("/enable")
    public ProblemReasonVO enable(@RequestBody ProblemReasonVO reasonVO) throws BusinessException{
        if(reasonVO == null) throw new BusinessException("传参错误");

        return maintain.enable(reasonVO);
    }

    /**
     * 从excel文件导入问题原因
     *
     * @param file 导入excel文件
     * @return 导入结果
     * @throws BusinessException
     */
    @PostMapping("/importFromExcel")
    public boolean importFromExcel(@RequestParam("file") MultipartFile file, @RequestParam("category") Integer category)
            throws BusinessException {
        try {
            List<List<String>> excelData = ExcelUtil.readExcel(file.getInputStream(), 3);
            List<ProblemReasonVO> rootVOs = manager.generateProbReasonFromExcelData(excelData);
            return maintain.insertFromExcel(rootVOs, category.byteValue());
        } catch (Exception e) {
            if (e instanceof BusinessException) {
                throw (BusinessException) e;
            } else {
                throw new BusinessException("问题原因导入出错", e);
            }
        }
    }

    @GetMapping("/referCheck")
    public boolean referCheck(@RequestParam("pkReason") String pkReason) throws BusinessException{

         return maintain.referenceCheck(pkReason);
    }

}
